#include "SerialPort_SerialPortFactory.h"
#include "SerialPortFactory.h"


boost::shared_ptr<SerialPortFactory> serialPortFactory;
extern JavaVM* g_jvm;

JNIEXPORT jint JNICALL Java_SerialPort_SerialPortFactory_initIoService(JNIEnv *penv, jobject) {
	if (serialPortFactory == NULL) {
		serialPortFactory.reset(new SerialPortFactory());
	}

	if (g_jvm == NULL) {
		int ret = penv->GetJavaVM(&g_jvm);
		std::cout << "init jvm fail:" << ret<<std::endl;
		return ret;
	}

	serialPortFactory->init();

	return 0;
}

JNIEXPORT jint JNICALL Java_SerialPort_SerialPortFactory_runIoService
(JNIEnv *, jobject) {
	//std::cout<<"run"<<GetCurrentThreadId()<<std::endl;
	if (serialPortFactory == NULL) {
		return -1;
	}
	
	boost::system::error_code  ec;

	return serialPortFactory->run_one(ec);
}

JNIEXPORT void JNICALL Java_SerialPort_SerialPortFactory_closeService
(JNIEnv *, jobject) {
	if (serialPortFactory == NULL) {
		return;
	}

	serialPortFactory->close();
}



/*
* Class:     SerialPort_SerialPortFactory
* Method:    openSerialPortEx
* Signature: (Ljava/lang/String;JIIII)J
*/
JNIEXPORT jlong JNICALL Java_SerialPort_SerialPortFactory_openSerialPortEx
(JNIEnv *penv, jobject obj, jstring com, jlong baud, jint parity, jint stop, jint char_size, jint buf_size) {

	const char* str_com = penv->GetStringUTFChars(com, NULL);

	if (NULL == str_com) {
		return -1;
	}
	//LOGD("open serial port"); 
	//io_service_ptr ios = serialPortFactory->get_ios_ptr();
	//LOGD("open serial port get ios=%x",ios.get()); 
	serial_port_ptr sp(new serial_port(*serialPortFactory->get_ios_ptr().get(), str_com));
	//LOGD("open serial port finish"); 
	penv->ReleaseStringUTFChars(com, str_com);

    //LOGD("set serial port option"); 
	sp->set_option(serial_port::baud_rate(baud));
	sp->set_option(serial_port::flow_control());

	switch (parity) {
	case parity_none:
		sp->set_option(serial_port::parity(serial_port::parity::none));
		break;
	case parity_odd:
		sp->set_option(serial_port::parity(serial_port::parity::odd));
		break;
	case parity_even:
		sp->set_option(serial_port::parity(serial_port::parity::even));
		break;
	default:
		sp->set_option(serial_port::parity());
	}
	
	switch (stop) {
	case stop_one:
		sp->set_option(serial_port::stop_bits(serial_port::stop_bits::one));
		break;
	case stop_onePointFive:
		sp->set_option(serial_port::stop_bits(serial_port::stop_bits::onepointfive));
		break;
	case stop_two:
		sp->set_option(serial_port::stop_bits(serial_port::stop_bits::two));
		break;
	default:
		sp->set_option(serial_port::stop_bits());
	}
	
	sp->set_option(serial_port::character_size(char_size));

	jlong fd = (jlong)sp.get();
	serialPortFactory->insert_serial_info(fd, SerialPortInfoPtr(new SerialPortInfo(sp, buf_size)));

	return fd;
}

/*
 * Class:     SerialPort_SerialPortFactory
 * Method:    getCurrentThreadId
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_SerialPort_SerialPortFactory_getCurrentThreadId
  (JNIEnv *, jobject){
	  return GetCurrentThreadId();
}

